package com.gc.baselib.base

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavOptions
import androidx.navigation.fragment.findNavController
import androidx.viewbinding.ViewBinding
import com.gc.baselib.base.event.NavigationEvent
import com.gc.baselib.utils.SoftKeyBoardUtil
import com.gc.logger.LogUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.lang.reflect.ParameterizedType

abstract class BaseFragment<V : ViewBinding, VM : BaseViewModel> : Fragment(), IBaseView,
    MVVMProvider<VM> {
    protected lateinit var mBinding: V
    protected lateinit var mViewModel: VM
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        createViewModel()
        initParams(arguments)
//        Log.e("aaaaaaaa",)
        LogUtils.d("framwork","${this.javaClass.name}=======onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
//        Log.e("aaaaaaaa","${this.javaClass.name}=======onCreateView")
        mBinding = initViewBinding(inflater, container, false);
        initView()
        return mBinding.root
    }

    private fun initViewBinding(inflater: LayoutInflater, container: ViewGroup?, b: Boolean): V {
        val superClass = javaClass.genericSuperclass
        if (superClass is ParameterizedType) {
            val type = superClass.actualTypeArguments[0]
            val clazz = type as Class<V>
            val declaredMethod = clazz.getDeclaredMethod(
                "inflate",
                LayoutInflater::class.java,
                ViewGroup::class.java,
                Boolean::class.java
            )
            val bingding = declaredMethod.invoke(null, inflater, container, false)
            return bingding as V;
        } else {
            throw IllegalArgumentException("ParameterizedType error")
        }


    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
//        Log.e("aaaaaaaa","${this.javaClass.name}=======onViewCreated")
        initViewDataBinding()
        initCommonEventBinding()
        //页面事件监听的方法，一般用于ViewModel层转到View层的事件注册
        initObservable()
        initData()

    }

    open fun initData() {

    }

    open fun initObservable() {

    }

    /***
     * 初始化ViewModel与DataBinding
     */
    private fun initViewDataBinding() {
        lifecycleOwner().lifecycle.addObserver(mViewModel)
    }


    /**
     * 常用事件绑定
     */
    private fun initCommonEventBinding() {
        mViewModel.commonEvent.finishEvent.observe(
            lifecycleOwner()
        ) { onFinish() }
        mViewModel.commonEvent.backEvent.observe(
            lifecycleOwner()
        ) { onBackPressed() }
        mViewModel.commonEvent.navEvent.observe(
            lifecycleOwner()
        ) { event: NavigationEvent? ->
            if (event != null) {
                openNavigation(
                    event
                )
            }
        }
        mViewModel.commonEvent.toastEvent.observe(
            lifecycleOwner()
        ) { content: String? ->
            Toast.makeText(
                activity,
                content,
                Toast.LENGTH_SHORT
            ).show()
        }
        mViewModel.commonEvent.softKeyBoardShowEvent.observe(
            lifecycleOwner()
        ) { aBoolean: Boolean ->
            if (aBoolean) {
                SoftKeyBoardUtil.showSoftKeyboard(activity)
            } else {
                SoftKeyBoardUtil.hideKeyBoard(activity)
            }
        }
    }

    protected open fun onFinish() {
        activity?.finish()
    }

    protected open fun onBackPressed() {
        activity?.onBackPressed()
    }

    protected open fun openNavigation(event: NavigationEvent) {
        if (event.navType == NavigationEvent.Nav_Type_Activity) {
            val intent = Intent(activity, event.clazz)
            if (event.bundle != null) {
                intent.putExtras(event.bundle)
            }
            if(event.isClearAll){
                ActivityManager.getInstance().finishAll()
            }else{
                if(event.isCloseSelf){
                    activity?.finish()
                }
            }
            if (event.reqCode > 0) {
                startActivityForResult(intent, event.reqCode)
            } else {
                startActivity(intent)
            }


        } else if (event.navType == NavigationEvent.Nav_Type_Fragment) {
//            val navOptions = NavOptions.Builder().setPopUpTo()
            findNavController()?.let{
                var navOptions: NavOptions? =null
                event.isCloseSelf?.let{
                    if(event.isCloseSelf){
                        val id = findNavController().currentDestination?.id
                        navOptions= id?.let { it1 ->
                            NavOptions.Builder()
                                .setPopUpTo(it1, inclusive = true, saveState = false)
                                .build()
                        }
                    }
                }
                it.navigate(event.navId, event.bundle,navOptions)
            }
//            NavHostFragment.findNavController(this).navigate(event.navId, event.bundle)
        }
    }

    override fun initParams(extras: Bundle?) {

    }

    override fun initNewIntentParams(extras: Bundle?) {
        //TODO("Not yet implemented")
    }

    private fun createViewModel() {
        mViewModel = initViewModel()

    }

    override fun initViewModel(): VM {
        val modelClass: Class<VM>
        val type = javaClass.genericSuperclass
        modelClass = if (type is ParameterizedType) {
            type.actualTypeArguments[1] as Class<VM>
        } else {
            //如果没有指定泛型参数，则默认使用BaseViewModel
            BaseViewModel::class.java as Class<VM>
        }
        return getViewModel(this, modelClass) as VM
    }

    open fun getViewModel(fragment: Fragment, clazz: Class<VM>): VM? {
        val factory =
            activity?.let { ViewModelProvider.AndroidViewModelFactory.getInstance(it.application) }
        return factory?.let { ViewModelProvider(fragment, it) }?.get(clazz)
    }

    override fun lifecycleOwner(): LifecycleOwner {
        return this
    }
    suspend fun toastShow(text: String?) = withContext(Dispatchers.Main) {
        Toast.makeText(activity, text, Toast.LENGTH_SHORT).show()
    }

    fun toastShortShow(text: String?) {
        Toast.makeText(activity, text, Toast.LENGTH_SHORT).show()
    }

    override fun onStart() {
//        LogUtils.d("framework","${this.javaClass.name}=======onStart")
        super.onStart()
    }

    override fun onResume() {
        //LogUtils.d("framework","${this.javaClass.name}=======onResume")
        super.onResume()
    }

    override fun onPause() {
       // LogUtils.d("framework","${this.javaClass.name}=======onPause")
        super.onPause()
    }

    override fun onStop() {
        //LogUtils.d("framework","${this.javaClass.name}=======onStop")
        super.onStop()
    }

    override fun onDestroy() {
        LogUtils.d("framework","${this.javaClass.name}=======onDestroy")
        super.onDestroy()
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        LogUtils.d("framework","${this.javaClass.name}=======onHiddenChanged $hidden")
    }

}